import json
import os
import re
from datetime import datetime

def merge_movie_data():
    """
    合并豆瓣和猫眼的电影数据，进行清洗和去重，
    并保存为可供Vue前端使用的JSON文件。
    """
    print("="*60)
    print("电影数据分析系统 - 数据合并工具")
    print("="*60)
    print("\n本工具将：")
    print("1. 加载豆瓣和猫眼的电影数据")
    print("2. 进行数据清洗、合并和去重")
    print("3. 生成统一格式的电影数据供前端使用")
    print("="*60)
    
    # --- 文件路径定义 ---
    douban_file = os.path.join('douban_data', 'douban_top100_detailed.json')
    maoyan_file = os.path.join('maoyan_data', 'maoyan_top100_selenium.json')
    output_dir = os.path.join('vue-dashboard', 'src', 'data')
    output_file = os.path.join(output_dir, 'movies.json')

    # --- 加载数据 ---
    douban_movies = load_json_file(douban_file, "豆瓣")
    if not douban_movies:
        return
        
    maoyan_movies = load_json_file(maoyan_file, "猫眼")
    if not maoyan_movies:
        return

    # --- 数据清洗和合并 ---
    # 使用字典以电影标题作为唯一键，方便去重
    merged_movies = {}
    movie_id_counter = 1  # 为每部电影分配唯一ID

    # 1. 处理豆瓣数据
    print("\n处理豆瓣电影数据...")
    for movie in douban_movies:
        try:
            title = clean_text(movie.get('title', ''))
            if not title:
                continue
            
            # 清洗和提取核心字段
            rating = clean_rating(movie.get('rating'))
            year = extract_year(movie.get('year'))
            
            merged_movies[title] = {
                'id': movie_id_counter,
                'rank': movie.get('rank'),
                'title': title,
                'rating': rating,
                'genres': clean_list(movie.get('genres', [])),
                'directors': clean_list(movie.get('directors', [])),
                'actors': clean_list(movie.get('actors', []))[:20],  # 限制演员数量
                'year': year,
                'countries': clean_list(movie.get('countries', [])),
                'plot_summary': clean_text(movie.get('plot_summary', movie.get('intro', ''))),
                'source': 'Douban',
                'rankings': {'Douban': movie.get('rank')}
            }
            movie_id_counter += 1
        except Exception as e:
            print(f"处理豆瓣电影 '{movie.get('title', '未知')}' 时出错: {e}")

    # 2. 处理猫眼数据
    print("处理猫眼电影数据...")
    for movie in maoyan_movies:
        try:
            title = clean_text(movie.get('title', ''))
            if not title:
                continue
            
            # 如果电影不存在于豆瓣数据中，则添加猫眼的数据
            if title not in merged_movies:
                # 清洗和提取数据
                year = extract_year(movie.get('release_time', ''))
                rating = clean_rating(movie.get('score'))
                
                # 处理导演信息
                directors = []
                if movie.get('director'):
                    directors = [clean_text(d) for d in movie.get('director').split(',')]
                
                # 处理国家/地区信息
                countries = []
                if movie.get('area_duration'):
                    parts = movie.get('area_duration').split('/')
                    if parts and len(parts) > 0:
                        countries = [clean_text(c) for c in parts[0].split(',')]
                
                # 处理类型信息
                genres = []
                if movie.get('category'):
                    genres = [clean_text(g) for g in movie.get('category').split(',')]
                
                # 处理演员信息
                actors = []
                if movie.get('stars'):
                    actors = [clean_text(a) for a in movie.get('stars').split(',')]
                    actors = actors[:20]  # 限制演员数量
                
                merged_movies[title] = {
                    'id': movie_id_counter,
                    'rank': movie.get('rank'),
                    'title': title,
                    'rating': rating,
                    'genres': genres,
                    'directors': directors,
                    'actors': actors,
                    'year': year,
                    'countries': countries,
                    'plot_summary': clean_text(movie.get('summary', '')),
                    'source': 'Maoyan',
                    'rankings': {'Maoyan': movie.get('rank')}
                }
                movie_id_counter += 1
            # 如果电影已存在，合并数据
            else:
                existing_movie = merged_movies[title]
                
                # 添加猫眼排名信息
                if 'rankings' not in existing_movie:
                    existing_movie['rankings'] = {}
                existing_movie['rankings']['Maoyan'] = movie.get('rank')
                
                # 补充导演信息（如果豆瓣数据缺失）
                if not existing_movie.get('directors') and movie.get('director'):
                    directors = [clean_text(d) for d in movie.get('director').split(',')]
                    existing_movie['directors'] = directors
                
                # 补充演员信息（如果豆瓣数据缺失）
                if not existing_movie.get('actors') and movie.get('stars'):
                    actors = [clean_text(a) for a in movie.get('stars').split(',')]
                    existing_movie['actors'] = actors[:20]
                
                # 补充剧情简介（如果豆瓣数据缺失）
                if not existing_movie.get('plot_summary') and movie.get('summary'):
                    existing_movie['plot_summary'] = clean_text(movie.get('summary'))
                
                # 如果豆瓣没有评分但猫眼有，使用猫眼的评分
                if existing_movie.get('rating') is None and movie.get('score'):
                    existing_movie['rating'] = clean_rating(movie.get('score'))
        except Exception as e:
            print(f"处理猫眼电影 '{movie.get('title', '未知')}' 时出错: {e}")

    # --- 数据验证和后处理 ---
    print("\n进行数据验证和后处理...")
    final_movie_list = []
    invalid_count = 0
    
    for title, movie in merged_movies.items():
        try:
            # 基本数据验证
            if not movie.get('title') or not isinstance(movie.get('title'), str):
                print(f"警告: 电影 ID {movie.get('id', '未知')} 标题无效，跳过")
                invalid_count += 1
                continue
                
            # 确保评分是数值类型
            if movie.get('rating') is not None and not isinstance(movie.get('rating'), (int, float)):
                try:
                    movie['rating'] = float(movie['rating'])
                except (ValueError, TypeError):
                    print(f"警告: 电影 '{title}' 评分格式无效，设为空")
                    movie['rating'] = None
            
            # 确保年份是整数
            if movie.get('year') is not None and not isinstance(movie.get('year'), int):
                try:
                    movie['year'] = int(movie['year'])
                except (ValueError, TypeError):
                    print(f"警告: 电影 '{title}' 年份格式无效，设为空")
                    movie['year'] = None
            
            # 确保列表字段是列表类型
            for field in ['genres', 'directors', 'actors', 'countries']:
                if not isinstance(movie.get(field), list):
                    movie[field] = []
            
            # 计算综合排名因子
            # 1. 首先考虑原始排名
            ranking_factor = 0
            rankings = movie.get('rankings', {})
            
            # 计算豆瓣和猫眼排名的加权平均（豆瓣权重更高）
            if 'Douban' in rankings and 'Maoyan' in rankings:
                # 两个平台都有排名，加权平均（豆瓣:猫眼 = 7:3）
                ranking_factor = (rankings['Douban'] * 0.7 + rankings['Maoyan'] * 0.3)
            elif 'Douban' in rankings:
                # 只有豆瓣排名
                ranking_factor = rankings['Douban']
            elif 'Maoyan' in rankings:
                # 只有猫眼排名
                ranking_factor = rankings['Maoyan']
            else:
                # 没有任何排名信息，使用一个大数字
                ranking_factor = 999
            
            # 2. 然后考虑评分（评分越高，排名越靠前）
            rating = movie.get('rating') or 0
            
            # 3. 再考虑数据来源（优先使用豆瓣数据）
            source_factor = 0 if movie.get('source') == 'Douban' else 0.1
            
            # 4. 最后考虑电影年份（新电影略微靠前）
            year = movie.get('year') or 2000
            year_factor = (2025 - year) / 100  # 年份因子，影响较小
            
            # 保存排序因子供排序使用
            movie['_ranking_factor'] = ranking_factor
            movie['_combined_factor'] = ranking_factor + (10 - rating) * 2 + source_factor + year_factor
            
            final_movie_list.append(movie)
        except Exception as e:
            print(f"验证电影 '{title}' 时出错: {e}")
            invalid_count += 1

    # 使用综合排序因子排序
    print("按综合因子排序电影...")
    final_movie_list = sorted(final_movie_list, key=lambda x: x.get('_combined_factor', 999))
    
    # 重新分配排名
    for i, movie in enumerate(final_movie_list, 1):
        movie['rank'] = i
        # 删除临时排序因子
        if '_ranking_factor' in movie:
            del movie['_ranking_factor']
        if '_combined_factor' in movie:
            del movie['_combined_factor']

    # --- 保存结果 ---
    # 确保输出目录存在
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    try:
        # 保存为JSON文件
        with open(output_file, 'w', encoding='utf-8') as f:
            json.dump(final_movie_list, f, ensure_ascii=False, indent=4)
            
        print("\n" + "="*60)
        print("数据合并完成！")
        print(f"共处理了 {len(final_movie_list)} 条有效电影数据。")
        if invalid_count > 0:
            print(f"跳过了 {invalid_count} 条无效数据。")
        print(f"已将合并后的数据保存到: {output_file}")
        print("="*60)
    except Exception as e:
        print(f"\n错误: 保存合并数据失败: {e}")

def load_json_file(file_path, source_name):
    """加载JSON文件并处理可能的错误"""
    try:
        with open(file_path, 'r', encoding='utf-8-sig') as f:
            data = json.load(f)
        print(f"成功加载 {len(data)} 条{source_name}电影数据。")
        return data
    except FileNotFoundError:
        print(f"错误：找不到{source_name}数据文件 {file_path}")
        return None
    except json.JSONDecodeError:
        print(f"错误：解析{source_name}JSON文件失败 {file_path}")
        return None
    except Exception as e:
        print(f"错误：加载{source_name}数据时发生未知错误: {e}")
        return None

def clean_text(text):
    """清理文本，去除多余空格等"""
    if not text or not isinstance(text, str):
        return ""
    return text.strip()

def clean_list(items):
    """清理列表，确保所有元素都是有效的字符串"""
    if not items or not isinstance(items, list):
        return []
    return [clean_text(item) for item in items if item and isinstance(item, str)]

def clean_rating(rating):
    """统一处理评分格式"""
    if rating is None:
        return None
        
    # 如果是字符串类型，可能需要额外处理
    if isinstance(rating, str):
        # 检查是否包含"无评分"
        if "无评分" in rating:
            return None
            
        # 尝试提取第一个数值
        match = re.search(r'(\d+\.?\d*)', rating)
        if match:
            try:
                return float(match.group(1))
            except ValueError:
                return None
                
        # 如果没有找到数值，返回None
        return None
        
    # 尝试直接转换为浮点数
    try:
        return float(rating)
    except (ValueError, TypeError):
        return None

def extract_year(year_data):
    """从各种可能的年份数据中提取年份"""
    if not year_data:
        return None
        
    # 如果已经是整数，直接返回
    if isinstance(year_data, int):
        return year_data
        
    # 如果是字符串，尝试提取年份
    if isinstance(year_data, str):
        # 尝试直接转换
        try:
            return int(year_data)
        except ValueError:
            # 尝试使用正则表达式提取
            match = re.search(r'(\d{4})', year_data)
            if match:
                try:
                    return int(match.group(1))
                except ValueError:
                    pass
    
    # 如果无法提取，返回当前年份
    return datetime.now().year

if __name__ == '__main__':
    merge_movie_data() 